//日志器类——是对前面几个类的整合
#ifndef _M_LOGGER_H__
#define _M_LOGGER_H__

#include"format.hpp"
#include"logsink.hpp"
#include"looper.hpp"
#include<cstdarg>
#include<mutex>
#include<pthread.h>
#include<atomic>
#include<unordered_map>

namespace bitlog{
    class Logger{
        public:
        using ptr=shared_ptr<Logger>;
        Logger(const string& name,Formatter::ptr format,vector<LogSink::ptr> sinks,Loglevel::value level=Loglevel::value::DEBUG)
        :_name(name),_format(format),_sinks(sinks.begin(),sinks.end()),_limit_level(level)
        {}
        string get_logname(){
            return _name;
        }
        Loglevel::value get_limit_level(){
            return _limit_level;
        }
        void debug(string filename,size_t line,const char* fmt,...){
            if(Loglevel::value::DEBUG<_limit_level) return;
            va_list al;
            va_start(al,fmt);
            log(Loglevel::value::DEBUG,filename,line,fmt,al);
            va_end(al);
        }
        void info(string filename,size_t line,const char* fmt,...){
            if(Loglevel::value::INFO<_limit_level) return;
            va_list al;
            va_start(al,fmt);
            log(Loglevel::value::INFO,filename,line,fmt,al);
            va_end(al);
        }
        void warning(string filename,size_t line,const char* fmt,...){
            if(Loglevel::value::WARNING<_limit_level) return;
            va_list al;
            va_start(al,fmt);
            log(Loglevel::value::WARNING,filename,line,fmt,al);
            va_end(al);
        }
        void error(string filename,size_t line,const char* fmt,...){
            if(Loglevel::value::ERROR<_limit_level) return;
            va_list al;
            va_start(al,fmt);
            log(Loglevel::value::ERROR,filename,line,fmt,al);
            va_end(al);
        }
        void fatal(string filename,size_t line,const char* fmt,...){
            if(Loglevel::value::FATAL<_limit_level) return;
            va_list al;
            va_start(al,fmt);
            log(Loglevel::value::FATAL,filename,line,fmt,al);
            va_end(al);
        }
        protected:
        void log(Loglevel::value limit,string filename,size_t line,const char* fmt,va_list al){
            char* buf;
            string msg;
            int len=vasprintf(&buf,fmt,al);
            if(len<0){
                msg="格式化日志消息失败";
            }else{
                msg.assign(buf,len);
                free(buf);
            }
            LogMsg msg1(_name,limit,filename,line,msg);
            string ret=_format->format(msg1);
            logIt(move(ret));
        }
        virtual void logIt(const string& msg)=0;
        protected:
        mutex _mutex;
        string _name;
        atomic<Loglevel::value> _limit_level;
        Formatter::ptr _format;
        vector<LogSink::ptr> _sinks;
    };
    class Synclogger:public Logger{
        public:
        using ptr=shared_ptr<Synclogger>;
        Synclogger(const string& name,Formatter::ptr format,vector<LogSink::ptr> sinks,Loglevel::value level=Loglevel::value::DEBUG)
        :Logger(name,format,sinks,level){
            cout<<Loglevel::toString(level)<<"同步日志器："<<name<<"创建成功..."<<endl;
        }
        private:
        void logIt(const string& msg){
            unique_lock<mutex> lock(_mutex);
            if(_sinks.empty()) return;
            for(auto& it:_sinks){
                it->log(msg.c_str(),msg.size());
            }
        }
    };
    class Asynclogger:public Logger{
        public:
        using ptr=shared_ptr<Asynclogger>;
        Asynclogger(const string& name,Formatter::ptr format,vector<LogSink::ptr> sinks,Loglevel::value level=Loglevel::value::DEBUG)
        :Logger(name,format,sinks,level),_looper(make_shared<Asynclooper>(bind(&Asynclogger::reallog,this,placeholders::_1)))
        {
            cout<<Loglevel::toString(level)<<"异步日志器："<<name<<"创建成功..."<<endl;
        }
        protected:
        void logIt(const string& msg){
            _looper->push(msg);
        }
        void reallog(Buffer& buffer){
            if(_sinks.empty()) return;
            for(auto& it:_sinks){
                it->log(buffer.begin(),buffer.readAblesize());
            }
        }
        private:
        Asynclooper::ptr _looper;
    };
    enum class Type{
        LOGGER_SYNC=0,
        LOGGER_ASYNC
    };
    class Builder{
        public:
        using ptr=shared_ptr<Builder>;
        Builder():_logger_type(Type::LOGGER_SYNC),_limit_level(Loglevel::value::DEBUG)
        {}
        void buildLoggerName(const string& name) {_name=name;}
        void buildLimitLevel(Loglevel::value level) {_limit_level=level;}
        void buildLoggerType(Type type) {_logger_type=type;}
        void buildFormatter(const string& pattern){
            _format=make_shared<Formatter>(pattern);
        }
        template<typename Sinktype,typename ...Args>
        void buildSink(Args... args){
            auto sink=SinkFactor::createSink<Sinktype>(forward<Args>(args)...);
            _sinks.push_back(sink);
        }
        virtual Logger::ptr build()=0;
        protected:
        Type _logger_type;
        string _name;
        Loglevel::value _limit_level;
        Formatter::ptr _format;
        vector<LogSink::ptr> _sinks;
    };
    class LocalLoggerBuilder:public Builder{
        public:
        Logger::ptr build() override{
            if(_name.empty()){
                cout<<"日志器名字不能为空"<<endl;
                abort();
            }
            if(_format.get()==nullptr){
                cout<<"当前日志器："<<_name<<" 未检测到日志格式，";
                cout<<"使用默认的输出格式：%d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n\n";
                _format=make_shared<Formatter>();
            }
            if(_sinks.empty()){
                cout<<"当前日志器："<<_name<<"没有检测到落地方向";
                cout<<"使用默认的落地方向: StdoutSink\n";
                auto sink=SinkFactor::createSink<StdoutSink>();
                _sinks.push_back(sink);
            }
            Logger::ptr lp;
            if(_logger_type==Type::LOGGER_SYNC){
                lp=make_shared<Synclogger>(_name,_format,_sinks,_limit_level);
            }else{
                lp=make_shared<Asynclogger>(_name,_format,_sinks,_limit_level);
            }
            return lp;
        }
    };
    class loggerManager{
        private:
        mutex _mutex;
        Logger::ptr _root_logger;
        unordered_map<string,Logger::ptr> _loggers;
        private:
        loggerManager(){
            unique_ptr<Builder> sl(new LocalLoggerBuilder());
            sl->buildLoggerName("root");
            sl->buildLoggerType(Type::LOGGER_SYNC);
            _root_logger=sl->build();
            _loggers.insert(make_pair("root",_root_logger));
        }
        loggerManager(const loggerManager&)=delete;
        loggerManager operator&=(const loggerManager&)=delete;
        public:
        static loggerManager& getInstance(){
            static loggerManager lm;
            return lm;
        }
        bool hasLogger(const string& name){
            unique_lock<mutex> lock(_mutex);
            auto it=_loggers.find(name);
            if(it==_loggers.end()){
                return false;
            }
            return true;
        }
        void addLogger(const string& name,Logger::ptr& logger){
            unique_lock<mutex> lock(_mutex);
            _loggers.insert(make_pair(name,logger));
        }
        Logger::ptr getLogger(const string& name){
            unique_lock<mutex> lock(_mutex);
            auto it=_loggers.find(name);
            if(it==_loggers.end()){
                return Logger::ptr();
            }
            return it->second;
        }
        Logger::ptr getrootLogger(){
            unique_lock<mutex> lock(_mutex);
            return _root_logger;
        }
    };
    class GlobalLoggerBuilder:public Builder{
        public:
        Logger::ptr build() override{
            if(_name.empty()){
                cout<<"日志器名字不能为空"<<endl;
                abort();
            }
            assert(loggerManager::getInstance().hasLogger(_name)==false);
            if(_format.get()==nullptr){
                cout<<"当前日志器："<<_name<<" 未检测到日志格式，";
                cout<<"使用默认的输出格式：%d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n\n";
                _format=make_shared<Formatter>();
            }
            if(_sinks.empty()){
                cout<<"当前日志器："<<_name<<"没有检测到落地方向";
                cout<<"使用默认的落地方向: StdoutSink";
                auto sink=SinkFactor::createSink<StdoutSink>();
                _sinks.push_back(sink);
            }
            Logger::ptr lp;
            if(_logger_type==Type::LOGGER_SYNC){
                lp=make_shared<Synclogger>(_name,_format,_sinks,_limit_level);
            }else{
                lp=make_shared<Asynclogger>(_name,_format,_sinks,_limit_level);
            }
            loggerManager::getInstance().addLogger(_name,lp);
            return lp;
        }
    }; 
}


#endif